
package com.example.videotrim;

import com.example.videotrim.utils.BitmapCache;
import com.example.videotrim.utils.S3dVideo;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.provider.MediaStore;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;

import java.io.File;

public class VideoChooser extends Activity implements OnItemClickListener, OnItemLongClickListener {
    private final static String TAG = "VideoChooser";

    private Cursor mCursor = null;

    private Bitmap mDefaultThumbnail = null;

    private BroadcastReceiver mBroadcastReceiver = null;

    private int mItemIndexForOperations = -1;

    private BitmapCache mBitmapCache = new BitmapCache();

    public static final int RESULT_TRIM_OVERWRITE = RESULT_FIRST_USER + 1;

    public static final int RESULT_TRIM_CREATE = RESULT_FIRST_USER + 2;

    private static final int DIALOG_ID_OPERATIONS = 0x1;

    private static final int DIALOG_ID_DELETE_CONFIRM = 0x2;

    private static final int DIALOG_ID_RENAME_INPUT = 0x3;

    private static final int DIALOG_ID_RENAME_WARNING = 0x4;

    private static final int DIALOG_ID_NOVIDEO_WARNING = 0x5;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.video_list_chooser);
        ListView listView = (ListView) this.findViewById(R.id.list_view);

        String[] mediaColumns = {
                MediaStore.Video.Media._ID, MediaStore.Video.Media.DATA,
                MediaStore.Video.Media.TITLE, MediaStore.Video.Media.DISPLAY_NAME,
                MediaStore.Video.Media.SIZE, MediaStore.Video.Media.MIME_TYPE,
                MediaStore.Video.VideoColumns.DURATION, MediaStore.Video.VideoColumns.RESOLUTION
        };

        mCursor = managedQuery(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, mediaColumns, null,
                null, null);

        if (mCursor == null || mCursor.getCount() == 0)
            showDialog(DIALOG_ID_NOVIDEO_WARNING);

        mDefaultThumbnail = BitmapFactory.decodeResource(getResources(), R.drawable.video);

        String from[] = {
                MediaStore.Video.Media.DATA, MediaStore.Video.Media.SIZE,
                MediaStore.Video.VideoColumns.DURATION, MediaStore.Video.VideoColumns.RESOLUTION
        };

        int to[] = {
                R.id.title_view, R.id.size_view, R.id.duration_view, R.id.resolution_view
        };

        listView.setAdapter(new SimpleCursorAdapter(this, R.layout.list_view_entry, mCursor, from,
                to) {
            public void bindView(View view, Context context, Cursor cursor) {
                super.bindView(view, context, cursor);

                TextView titleView = (TextView) view.findViewById(R.id.title_view);
                File file = new File((String) titleView.getText());
                String fileName = file.getName();
                Log.i(TAG, "bindView --> fileName:" + fileName);
                if (fileName.equals(""))
                    return;
                String fileNameWithoutExt = fileName.substring(fileName
                        .lastIndexOf(File.separatorChar) + 1, fileName.lastIndexOf('.'));
                String fileExt = fileName.substring(fileName.lastIndexOf('.') + 1);
                titleView.setText(fileNameWithoutExt);
                TextView extView = (TextView) view.findViewById(R.id.ext_view);
                extView.setText(fileExt);

                TextView sizeView = (TextView) view.findViewById(R.id.size_view);
                try {
                    int size = Integer.parseInt((String) sizeView.getText());
                    if (size < 1024 * 1024)
                        sizeView.setText(String.format("%d KB", size / 1024));
                    else
                        sizeView.setText(String.format("%d MB", size / (1024 * 1024)));
                } catch (NumberFormatException e) {
                }

                TextView durationView = (TextView) view.findViewById(R.id.duration_view);
                try {
                    int sec = Integer.parseInt((String) durationView.getText()) / 1000;
                    durationView.setText(String.format("%02d:%02d:%02d", sec / (60 * 60), sec / 60,
                            sec % 60));
                } catch (NumberFormatException e) {
                }

                long mediaId = cursor.getLong(cursor.getColumnIndex(MediaStore.Video.Media._ID));
                Bitmap thumbBitmap = mBitmapCache.getBitmapFromCache(Long.toString(mediaId));
                ImageView thumbnailView = (ImageView) view.findViewById(R.id.image_view);

                if (thumbBitmap == null) {
                    thumbBitmap = mDefaultThumbnail;
                    getThumbnailInBackground(mediaId, thumbnailView);
                }

                mBitmapCache.addBitmapToCache(Long.toString(mediaId), thumbBitmap);
                thumbnailView.setImageBitmap(thumbBitmap);
            }

            private void getThumbnailInBackground(long mediaId, ImageView thumbnailView) {
                Log.v(TAG, "getThumbnailInBackground --> mediaId:" + mediaId);
                Handler handler = new Handler();
                new Thread(new ThumbnailExtractor(handler, VideoChooser.this, mediaId,
                        thumbnailView)).start();
            }
        });

        listView.setOnItemClickListener(this);
        listView.setOnItemLongClickListener(this);

        mBroadcastReceiver = new BroadcastReceiver() {
            public void onReceive(Context context, Intent intent) {
                VideoChooser.this.mCursor.requery();
            }
        };

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
        intentFilter.addDataScheme("file");
        registerReceiver(mBroadcastReceiver, intentFilter);
    }

    protected void onDestroy() {
        super.onDestroy();
        if (mBroadcastReceiver != null) {
            unregisterReceiver(mBroadcastReceiver);
        }
        mBitmapCache.clearCache();
    }

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Log
                .v(TAG, "onActivityResult --> requestCode:" + requestCode + ", resultCode:"
                        + resultCode);

        if (resultCode == RESULT_TRIM_OVERWRITE) {
            long mediaId = data.getLongExtra("mediaId", -1);
            if (mediaId != -1) {
                mBitmapCache.removeBitmapFromCache(Long.toString(mediaId));
            }
        } else if (resultCode == RESULT_TRIM_CREATE) {
        }
    }

    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.vid_chooser_menu, menu);
        return true;
    }

    public boolean onOptionsItemSelected(MenuItem item) {
        int itemId = item.getItemId();

        if (itemId == R.id.rescan) {
            StringBuffer path = new StringBuffer("file://");
            File dir = Environment.getExternalStorageDirectory();
            Uri uri = Uri.parse(path.append(dir).toString());
            Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED, uri);
            sendBroadcast(intent);
            mBitmapCache.clearCache();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    protected Dialog onCreateDialog(int id) {
        Dialog dialog = null;
        AlertDialog.Builder builder;

        switch (id) {
            case DIALOG_ID_OPERATIONS:
                final CharSequence items[] = new CharSequence[3];
                items[0] = getString(R.string.trim);
                items[1] = getString(R.string.rename);
                items[2] = getString(R.string.delete);

                builder = new AlertDialog.Builder(this);
                builder.setTitle(R.string.operations);
                builder.setNegativeButton(R.string.cancel, null);
                builder.setItems(items, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        switch (which) {
                            case 0:
                                if (mItemIndexForOperations > -1)
                                    doTrimActionOnListItem(mItemIndexForOperations);
                                break;
                            case 1:
                                showDialog(DIALOG_ID_RENAME_INPUT);
                                break;
                            case 2:
                                showDialog(DIALOG_ID_DELETE_CONFIRM);
                                break;
                        }
                    }
                });
                dialog = builder.create();
                break;
            case DIALOG_ID_DELETE_CONFIRM:
                builder = new AlertDialog.Builder(this);
                builder.setTitle(R.string.delete);
                builder.setMessage(R.string.delete_confirm);
                builder.setNegativeButton(R.string.cancel, null);
                builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        doDeleteActionOnListItem(mItemIndexForOperations);
                    }
                });
                dialog = builder.create();
                break;
            case DIALOG_ID_RENAME_INPUT:
                View renameView = LayoutInflater.from(this).inflate(R.layout.video_rename, null);
                builder = new AlertDialog.Builder(this);
                builder.setTitle(R.string.rename);
                builder.setView(renameView);
                builder.setNegativeButton(R.string.cancel, null);
                builder.setPositiveButton(R.string.rename, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        EditText newNameWidget = (EditText) ((AlertDialog) dialog)
                                .findViewById(R.id.new_video_name);
                        String newNameString = newNameWidget.getText().toString();
                        if (doRenameActionOnListItem(mItemIndexForOperations, newNameString) == false)
                            showDialog(DIALOG_ID_RENAME_WARNING);
                    }
                });
                dialog = builder.create();
                break;
            case DIALOG_ID_RENAME_WARNING:
                builder = new AlertDialog.Builder(this);
                builder.setTitle(R.string.warning);
                builder.setMessage(R.string.rename_failed);
                builder.setPositiveButton(R.string.ok, null);
                dialog = builder.create();
                break;
            case DIALOG_ID_NOVIDEO_WARNING:
                builder = new AlertDialog.Builder(this);
                builder.setTitle(R.string.warning);
                builder.setMessage(R.string.no_video);
                builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        //finish();
                    }
                });
                dialog = builder.create();
                break;
            default:
                break;
        }

        return dialog;
    }

    protected void onPrepareDialog(int id, Dialog dialog) {
        if (id == DIALOG_ID_RENAME_INPUT) {
            EditText editText = (EditText) dialog.findViewById(R.id.new_video_name);
            TextView textView = (TextView) dialog.findViewById(R.id.video_extension);

            if (mCursor.moveToPosition(mItemIndexForOperations)) {
                int fileColumn = mCursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
                String videoFilePath = mCursor.getString(fileColumn);
                File origFile = new File(videoFilePath);
                String origFileName = origFile.getName();
                String origFileNameWithoutExt = origFileName.substring(origFileName
                        .lastIndexOf(File.separatorChar) + 1, origFileName.lastIndexOf('.'));
                String fileExt = origFileName.substring(origFileName.lastIndexOf('.') + 1);
                editText.setText(origFileNameWithoutExt);
                textView.setText("." + fileExt);
            }
        }

        super.onPrepareDialog(id, dialog);
    }

    public void onItemClick(AdapterView<?> l, View v, int position, long id) {
        doTrimActionOnListItem(position);
    }

    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
        mItemIndexForOperations = position;
        showDialog(DIALOG_ID_OPERATIONS);
        return true;
    }

    private void doTrimActionOnListItem(int cursorIndex) {
        if (mCursor.moveToPosition(cursorIndex)) {
            int fileColumn = mCursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
            int idColumn = mCursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID);

            String videoFilePath = mCursor.getString(fileColumn);
            long mediaId = mCursor.getLong(idColumn);

            Context context = this.getApplicationContext();
            File newFile = new File(videoFilePath);
            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.fromFile(newFile), context,
                    VideoTrimmer.class);
            intent.putExtra("mediaId", mediaId);
            startActivityForResult(intent, 0);
        }
    }

    private void doDeleteActionOnListItem(int cursorIndex) {
        if (mCursor.moveToPosition(cursorIndex)) {
            int idColumn = mCursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID);
            long mediaId = mCursor.getLong(idColumn);

            ContentResolver cr = getContentResolver();
            Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            StringBuffer sb = new StringBuffer("_ID=");
            String queryStatement = sb.append(mediaId).toString();

            int deletedRows = cr.delete(uri, queryStatement, null);
            if (deletedRows > 0)
                mBitmapCache.removeBitmapFromCache(Long.toString(mediaId));
        }
    }

    private boolean doRenameActionOnListItem(int cursorIndex, String newNameString) {
        boolean result = false;

        if (mCursor.moveToPosition(cursorIndex)) {
            int fileColumn = mCursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
            int idColumn = mCursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID);

            String originalPathFileWithExt = mCursor.getString(fileColumn);
            String newFileWithoutExt = newNameString;
            long mediaId = mCursor.getLong(idColumn);

            if (newFileWithoutExt.trim().equals("")) {
                result = false;
            } else {
                File origFile = new File(originalPathFileWithExt);
                String origFileName = origFile.getName();
                String parentPath = String.valueOf(origFile.getParentFile().getPath());
                StringBuilder sb = (new StringBuilder(parentPath)).append("/").append(
                        newFileWithoutExt).append(".");
                String fileExt = origFileName.substring(origFileName.lastIndexOf('.') + 1);
                String newFileName = sb.append(fileExt).toString();
                File newFile = new File(newFileName);

                if (newFile.exists()) {
                    result = false;
                } else {
                    if (!(new File(originalPathFileWithExt)).renameTo(newFile)) {
                        result = false;
                    } else {
                        ContentValues contentvalues = new ContentValues();
                        contentvalues.put("_data", newFileName);
                        ContentResolver cr = getContentResolver();
                        Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                        String queryStatement = (new StringBuilder("_ID=")).append(mediaId)
                                .toString();
                        int updatedRows = cr.update(uri, contentvalues, queryStatement, null);
                        if (updatedRows > 0)
                            result = true;
                    }
                }
            }
        }

        return result;
    }

    class ThumbnailExtractor implements Runnable {
        private static final String TAG = "ThumbnailExtractor";

        private Handler mHandler;

        private Context mContext;

        private long mMediaId;

        private ImageView mThumbnailImageView;

        private Bitmap mThumbnailBitmap;

        public ThumbnailExtractor(Handler handler, Context context, long mediaId,
                ImageView thumbnailImageView) {
            this.mHandler = handler;
            this.mContext = context;
            this.mMediaId = mediaId;
            this.mThumbnailImageView = thumbnailImageView;
            this.mThumbnailBitmap = null;
        }

        public void run() {
            Log.v(TAG, "run --> get thumbnail bitmap");
            mThumbnailBitmap = MediaStore.Video.Thumbnails.getThumbnail(mContext
                    .getContentResolver(), mMediaId, MediaStore.Video.Thumbnails.MICRO_KIND, null);

            try {
                S3dVideo s3dVideo = new S3dVideo(mContext, mMediaId);
                s3dVideo.init();
                if (s3dVideo.isS3dVideo())
                    mThumbnailBitmap = s3dVideo.getThumbnail(mThumbnailBitmap);
            } catch (Throwable e) {
                e.printStackTrace();
            }

            if (mThumbnailBitmap != null) {
                mHandler.post(new Runnable() {
                    public void run() {
                        Log.v(TAG, "run --> set thumbnail to ImageView");
                        mBitmapCache.addBitmapToCache(Long.toString(mMediaId), mThumbnailBitmap);
                        mThumbnailImageView.setImageBitmap(mThumbnailBitmap);
                    }
                });
            }
        }
    }
}
